
package gestion;

import dao.EntityAlreadyExistsException;
import dao.InexistantEntityException;
import dao.ObjectDAOI;
import entities.Categorie;
import entities.Client;
import entities.Commande;
import entities.CommandePK;
import entities.Produit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;

/**
 * EJB Stateless de Gestion : utilisation du DAO, donne une vision métier et simplifie les traitements pour le Contrôleur.
 * @author Alex
 */
@Stateless
public class Gestionnaire implements GestionnaireRemote {

    @EJB
    private ObjectDAOI dao;

    @Override
    public void creerClient(String nom, String prenom) throws EntityAlreadyExistsException
    {
        Client client = new Client(nom, prenom);
        dao.insert(client, client.getId());
    }

    @Override
    public void creerProduit(Integer reference, String nom, double prix, Integer idCategorie) throws InexistantEntityException, EntityAlreadyExistsException
    {
        Categorie categorie = (Categorie) dao.get(Categorie.class, idCategorie);

        Produit produit = new Produit(reference, nom, prix, categorie);

        dao.insert(produit, reference);

        //Sans cette ligne, un ajout de produit à une catégorie sera invisible si on demande la liste des produits de la catégorie sans redémarrer le serveur.
        categorie.addProduit(produit);
        //A faire une fois que le 'insert' a été validé
    }

    @Override
    public void creerCategorie(String libelle) throws EntityAlreadyExistsException
    {
        Categorie categorie = new Categorie(libelle);
        dao.insert(categorie, categorie.getId());
    }

    @Override
    public void creerCommande(int referenceProduit, int idClient, int quantity) throws InexistantEntityException, EntityAlreadyExistsException
    {
        Produit produit = (Produit) dao.get(Produit.class, referenceProduit);
        Client client = (Client) dao.get(Client.class, idClient);

        Commande commande = new Commande(new CommandePK(referenceProduit, idClient), quantity, new Date(), client, produit);

        dao.insert(commande, commande.getPkey());

        //Sans cette ligne, un ajout de commande pour un client sera invisible si on demande la liste des commandes de ce client sans redémarrer le serveur.
        client.addCommande(commande);
        //A faire une fois que le 'save' a été validé
    }

    @Override
    public List<?> getAll(Class objectType)
    {
        return dao.getAll(objectType);
    }

    @Override
    public Object get(Class objectType, Object id) throws InexistantEntityException
    {
        return dao.get(objectType, id);
    }

    @Override
    public List<Produit> getProduitsDeCategorie(int idCategorie) throws InexistantEntityException
    {
        Categorie categorie = (Categorie) dao.get(Categorie.class, idCategorie);
        return categorie.getProduits(); //cette ligne ne doit pas se situer côté Struts, sinon le LAZY ne fonctionnera pas.
    }    

    @Override
    public List<Commande> getCommandesDuClient(int idClient) throws InexistantEntityException
    {
        Client client = (Client) dao.get(Client.class, idClient);
        return client.getCommandes(); //cette ligne ne doit pas se situer côté Struts, sinon le LAZY ne fonctionnera pas.
    }
    
    @Override
    public List<Commande> getCommandesDuProduit(Produit produit)
    {
        //La liste des commandes du Produit n'est pas accessible depuis l'entité, il faut donc l'obtenir avec une requête.
        
        Map<String, Object> parameterList = new HashMap<String, Object>();

        parameterList.put("produit", produit);

        String query = "select object(o) from Commande as o where o.produit = :produit";

        return (List<Commande>) dao.getObjectsQuery(query, parameterList);
    }

    @Override
    public void modifierClient(Integer idClient, String nom, String prenom) throws InexistantEntityException
    {
        Client client = (Client) dao.get(Client.class, idClient);
        client.setNom(nom);
        client.setPrenom(prenom);
        dao.update(client);
    }

    @Override
    public void modifierCategorie(Integer idCategorie, String libelle) throws InexistantEntityException
    {
        Categorie categorie = (Categorie) dao.get(Categorie.class, idCategorie);
        categorie.setLibelle(libelle);
        dao.update(categorie);
    }

    @Override
    public void modifierProduit(Integer idProduit, String nom, Double prix, Integer idCategorie) throws InexistantEntityException
    {
        Produit produit = (Produit) dao.get(Produit.class, idProduit);
        produit.setNom(nom);
        produit.setPrix(prix);
        Categorie oldCategorie = produit.getCategorie();

        Categorie categorie = (Categorie) dao.get(Categorie.class, idCategorie);
        produit.setCategorie(categorie);

        dao.update(produit);

        categorie.addProduit(produit);

        //Il faut garder l'objet en mémoire à jour : le produit n'appartient plus à l'ancienne catégorie
        oldCategorie.removeProduit(produit);
    }

    @Override
    public void supprimerClient(Integer idClient) throws InexistantEntityException
    {
        Client client = (Client) dao.get(Client.class, idClient);

        //Suppression en cascade : Il faut d'abord supprimer les commandes du client
        for(Commande commande : client.getCommandes())
            dao.delete(commande);

        dao.delete(client);
    }

    @Override
    public void supprimerCategorie(Integer idCategorie) throws InexistantEntityException
    {
        Categorie categorie = (Categorie) dao.get(Categorie.class, idCategorie);

        //Suppression en cascade : Il faut d'abord supprimer les produits, et donc les commandes avant
        for(Produit produit : categorie.getProduits())
        {
            supprimerCommandesDuProduit(produit);
            dao.delete(produit);
        }

        dao.delete(categorie);
    }

    @Override
    public void supprimerProduit(Integer idProduit) throws InexistantEntityException
    {
        Produit produit = (Produit) dao.get(Produit.class, idProduit);
        Categorie categorie = (Categorie) dao.get(Categorie.class, produit.getCategorie().getId());

        //Suppression en cascade : il faut supprimer toutes les commandes avant de pouvoir supprimer le produit
        
        supprimerCommandesDuProduit(produit);
        dao.delete(produit);

        categorie.removeProduit(produit);
    }
    
    /**
     * Supprime les commandes d'un produit, ne devrait pas être appelé indépendamment d'une autre suppression
     * @param produit
     */
    private void supprimerCommandesDuProduit(Produit produit)
    {
        for(Commande commande : getCommandesDuProduit(produit))
        {
            //Il faut également supprimer la commande de la liste de l'acheteur
            Client acheteur = commande.getAcheteur();
            acheteur.removeCommande(commande);

            dao.delete(commande);
        }
    }   

}
